
package nsalt.func 

import chisel3._
import chisel3.util._
import chisel3.util.experimental.BoringUtils

import nsalt._

// MOU, Memory Order Unit. 
// https://github.com/OSCPU/NutShell/blob/fd86beadfc47f52973270ce6109edebd2a30363b/src/main/scala/nutcore/backend/fu/MOU.scala
// 
// MemOrder mainly responds for two instructions, FENCE.I and SFENCE.VMA.

class MemOrderPort extends FuncUnitPort {
  val ctrlFlow = Flipped(new CtrlFlowPort)
  val redirect = new RedirectPort
}

class MemOrder extends Module {
  val io = IO(new MemOrderPort)

  val valid = io.in.valid
  val src1 = io.in.bits.src1
  val src2 = io.in.bits.src2
  val oper = io.in.bits.oper

  def access(valid: Bool, src1: UInt, src2: UInt, oper: UInt): UInt = {
    this.valid := valid
    this.src1 := src1
    this.src2 := src2
    this.oper := oper
    io.out.bits
  }

  io.redirect.dest := io.ctrlFlow.pc + 4.U
  io.redirect.valid := valid
  io.redirect.wholeFlushed := 0.U

  val flushICache = valid && (oper === MemOrderOperType.fencei)

  val flushTLB = valid && (oper === MemOrderOperType.sfence_vma)

  io.out.bits := 0.U
  io.in.ready := true.B
  io.out.valid := valid
}
